package com.codeduck.config;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import org.apache.shardingsphere.infra.config.RuleConfiguration;
import org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.keygen.KeyGenerateStrategyConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;

import javax.sql.DataSource;
import java.sql.SQLException;
import java.util.*;

/**
 * 分库不分表
 *
 * @author: codeduck@163.com
 * @since: 2021-06-04
 */
//@Configuration
public class ShardingDatabaseConfig {

//    @Bean(name = "dataSource")
//    @Primary
    public DataSource dataSource() throws SQLException {
        ShardingRuleConfiguration shardingRuleConfig = createOrderShardingRuleConfiguration();
        Collection<RuleConfiguration> configurations = new LinkedList<>();
        // 可以加多个分片规则配置（在此配置分库分表规则）
        configurations.add(shardingRuleConfig);
        return ShardingSphereDataSourceFactory.createDataSource(createDataSourceMap(), configurations, new Properties());
    }

    private ShardingRuleConfiguration createOrderShardingRuleConfiguration() {
        // 生成配置入口对象
        ShardingRuleConfiguration result = new ShardingRuleConfiguration();

        // 绑定分片表规则
        result.getTables().add(getOrderTableRuleConfiguration());

        // 设置默认的分库策略: order_id搭配行表达式分片算法{INLINE} —— 可参考 https://shardingsphere.apache.org/document/current/cn/user-manual/shardingsphere-jdbc/configuration/built-in-algorithm/sharding/
        result.setDefaultDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("order_id", "standard_test_db"));
        Properties propsForDb = new Properties();
        propsForDb.setProperty("algorithm-expression", "ds_${order_id % 2}");
        result.getShardingAlgorithms() .put("standard_test_db", new ShardingSphereAlgorithmConfiguration("INLINE", propsForDb));

        // 自增列生成算法名称和配置
        result.getKeyGenerators().put("snowflake", new ShardingSphereAlgorithmConfiguration("SNOWFLAKE", getProperties()));
        return result;
    }

    private static ShardingTableRuleConfiguration getOrderTableRuleConfiguration() {
        // 设置分片表
        ShardingTableRuleConfiguration result = new ShardingTableRuleConfiguration("t_order" );
        // 设置业务主键的生成策略: 使用雪花算法生成业务主键
        result.setKeyGenerateStrategy(new KeyGenerateStrategyConfiguration("order_id", "snowflake"));
        return result;
    }

    private static Map<String, DataSource> createDataSourceMap() {
        Map<String, DataSource> dataSourceMap = new HashMap<>(16);

        // 配置第一个数据源
        HikariDataSource ds_0 = new HikariDataSource();
        ds_0.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds_0.setJdbcUrl("jdbc:mysql://192.168.2.123:3306/springboot-demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8");
        ds_0.setUsername("root");
        ds_0.setPassword("123456");

        // 配置第二个数据源
        HikariDataSource ds_1 = new HikariDataSource();
        ds_1.setDriverClassName("com.mysql.cj.jdbc.Driver");
        ds_1.setJdbcUrl("jdbc:mysql://192.168.2.124:3306/springboot-demo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&autoReconnect=true&failOverReadOnly=false&serverTimezone=GMT%2B8");
        ds_1.setUsername("root");
        ds_1.setPassword("123456");

        dataSourceMap.put("ds_0", ds_0);
        dataSourceMap.put("ds_1", ds_1);
        return dataSourceMap;
    }

    private static Properties getProperties() {
        Properties result = new Properties();
        result.setProperty("worker-id", "123");
        return result;
    }
}
